package model

import (
	"math/rand"
	"strconv"
	"sync"
	"time"
)

type Account struct {
	Id int64 `xorm:"pk autoincr"`
	IdCard int64
	IdCardName string
	Nickname string
	CreatedAt time.Time
	UpdatedAt time.Time
}

type IncomingTicket struct {
	TrainId int64
	TrainNumber string
	DepartureDate []string
	DepartureTime []string
	DepartureStation string
	Terminus string
	Votes int
	SeatTypeList []*TicketType
}

type Train struct {
	Id int64 `xorm:"pk autoincr"`
	TrainNumber string
	Column int
	SeatsRow int
	CreatedAt time.Time
	UpdatedAt time.Time
}

type TicketType struct {
	Id int64 `xorm:"pk autoincr"`
	Name string
	Votes int `xorm:"-"`
	TicketPrice int `xorm:"-"`
	CurrentA int `xorm:"-"`
	CurrentB int `xorm:"-"`
	CurrentC int `xorm:"-"`
	CurrentD int `xorm:"-"`
	CurrentE int `xorm:"-"`
	CreatedAt time.Time
	UpdatedAt time.Time
}

type SaveTicket struct {
	Id int64 `xorm:"pk autoincr"`
	TrainId int64
	TrainNumber string
	DepartureDateTime string
	DepartureStation string
	Terminus string
	Votes int
	CreatedAt time.Time
	UpdatedAt time.Time
}

type TicketSeatType struct {
	Id int64 `xorm:"pk autoincr"`
	TicketTypeId int64
	TicketTypeName string
	SaveTicketId int64
	Votes int
	TicketPrice int
	FirstCarriageNumber int
	CurrentA int
	CurrentB int
	CurrentC int
	CurrentD int
	CurrentE int
	CreatedAt time.Time
	UpdatedAt time.Time
}

type  Ticket struct {
	Id int64 `xorm:"pk autoincr"`
	AccountId int64
	IdCard int64
	IdCardName string
	TrainNumber string
	CarriageSeat string
	DepartureDateTime string
	SeatTypeId int64
	SeatTypeName string
	TicketPrice int
	DepartureStation string
	Terminus string
	CreatedAt time.Time
	UpdatedAt time.Time
}

type AdmissionTicket struct {
	Id int64 `xorm:"pk autoincr"`
	ScenicSpotId int64
	ScenicSpotName string
	SightseeingDate string
	Votes int
	CreatedAt time.Time
	UpdatedAt time.Time
}

type ScenicSpot struct {
	Id int64 `xorm:"pk autoincr"`
	Name string
	CreatedAt time.Time
	UpdatedAt time.Time
}

func (t *Ticket) NewTicket(it *IncomingTicket)(map[string]interface{}, error){

	for _, ddv := range it.DepartureDate{
		for _, dtv := range it.DepartureTime{
			var st SaveTicket
			st.TrainId = it.TrainId
			st.TrainNumber = it.TrainNumber
			st.DepartureDateTime = ddv+" "+dtv
			st.DepartureStation = it.DepartureStation
			st.Terminus = it.Terminus
			st.Votes = it.Votes
			st.CreatedAt = time.Now()
			st.UpdatedAt = time.Now()
			x.Insert(&st)

			for _, stv := range it.SeatTypeList{
				var tstv TicketSeatType
				tstv.TicketTypeId = stv.Id
				tstv.TicketTypeName = stv.Name
				tstv.SaveTicketId = st.Id
				tstv.Votes = stv.Votes
				tstv.TicketPrice = stv.TicketPrice
				tstv.CurrentA  = stv.CurrentA
				tstv.CurrentB = stv.CurrentB
				tstv.CurrentC = stv.CurrentC
				tstv.CurrentD = stv.CurrentD
				tstv.CurrentE = stv.CurrentE
				tstv.CreatedAt = time.Now()
				tstv.UpdatedAt = time.Now()
				x.Insert(&tstv)
			}
		}
	}
	return map[string]interface{}{"message":"成功", "code":200}, nil
}

func RandomNumber(length int)(int){

	var t int

	defer func(){
		if err := recover(); err != nil {
			t = 0
		}
	}()

	t = rand.Intn(length)
	return t
}

var lock sync.Mutex

func (t *Ticket) TicketPurchase(aList []*Account, st *SaveTicket, tst *TicketSeatType, seatList []string) (map[string]interface{}, error){

	lock.Lock()

	for _, a := range aList{
		var tn Train
		x.Id(st.TrainId).Get(&tn)

		var tv Ticket
		tv.AccountId = a.Id
		tv.IdCard = a.IdCard
		tv.IdCardName = a.IdCardName
		tv.TrainNumber = st.TrainNumber
		tv.DepartureDateTime = st.DepartureDateTime
		tv.SeatTypeId = tst.TicketTypeId
		tv.SeatTypeName = tst.TicketTypeName
		tv.TicketPrice = tst.TicketPrice
		tv.DepartureStation = st.DepartureStation
		tv.Terminus = st.Terminus


		random := rand.Intn(len(seatList))
		seat := seatList[random]
		var seatCoount int
		if seat == "A" {
			seatCoount = tst.CurrentA
			tst.CurrentA -= 1
		} else if seat == "B" {
			seatCoount = tst.CurrentB
			tst.CurrentB -= 1
		} else if seat == "C" {
			seatCoount = tst.CurrentC
			tst.CurrentC -= 1
		} else if seat == "D" {
			seatCoount = tst.CurrentD
			tst.CurrentD -= 1
		} else if seat == "E" {
			seatCoount = tst.CurrentE
			tst.CurrentE -= 1
		}

		if seatCoount%tst.Votes >= 0 {
			tv.CarriageSeat = strconv.Itoa(tst.FirstCarriageNumber+seatCoount/(tst.Votes/tn.Column/tn.SeatsRow)+1) + "号车厢" + " " + seat + strconv.Itoa(seatCoount%(tst.Votes/tn.Column/tn.SeatsRow)+1) + "座"
		} else {
			tv.CarriageSeat = strconv.Itoa(tst.FirstCarriageNumber+seatCoount/(tst.Votes/tn.Column/tn.SeatsRow)+1) + "号车厢" + " " + seat + strconv.Itoa(seatCoount+1)
		}
		seatList = append(seatList[:random], seatList[random+1:]...)

		x.Insert(&tv)

		st.Votes -= 1
		x.Id(st.Id).Update(st)

		tst.Votes -= 1
		x.Id(tst.Id).Update(tst)
	}

	lock.Unlock()

	return map[string]interface{}{"message":"成功", "code":200}, nil
}

func CreateAdmissionTicket(dList []string, atList []*AdmissionTicket, ssList []*ScenicSpot, v int)(map[string]interface{}, error){

	for _, ss := range ssList{
		for _, d := range dList{
			var at = AdmissionTicket{
				ScenicSpotId:    ss.Id,
				ScenicSpotName:  ss.Name,
				SightseeingDate: d,
				Votes:           v,
				CreatedAt:       time.Now(),
				UpdatedAt:       time.Now(),
			}
			x.Insert(&at)
		}
	}

	return map[string]interface{}{"message":"成功", "code":200}, nil
}

func QueryTrainInformation(ddt string, ds string, t string)([]*SaveTicket, error){

	var stList []*SaveTicket
	x.Where("departure_date_time like ?", ddt+"%").And("departure_station = ?", ds).And("terminus = ?", t).Find(&stList)

	return stList, nil
}


































